package com.wengu.algorithm.alg;

import com.wengu.algorithm.dto.TaskAlg;
import com.wengu.algorithm.dto.UserAlg;
import com.wengu.algorithm.entity.AssignmentOutcome;
import com.wengu.algorithm.service.AssignmentOutcomeUserService;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class Genetic extends QEA {
    // 遗传算法参数
    private int populationSize = 100;
    private double crossoverRate = 0.8;
    private double mutationRate = 0.1;
    private int elitismCount = 5;
    private int maxGenerations = 100;

    // 从QEA继承的参数
    public double alpha;
    public double sigma;
    public double gamma;
    public double mu;

    // 存储所有任务的引用
    private List<TaskAlg> currentAllTasks;



    public Genetic(double alpha) {
        this.alpha = alpha;
    }

    public Genetic() {
        this(0.5); // 默认alpha值
    }
    /**
     * 主分配方法 - 使用遗传算法进行任务分配
     */
    public List<TaskAlg> allocateTasks(UserAlg user, List<TaskAlg> allTasks,
                                       AssignmentOutcome assignmentOutcome,
                                       AssignmentOutcomeUserService assignmentOutcomeUserService, Map<Long, TaskAlg> taskCacheMap, String algName, Set<Long> notIncreaseTaskIdSet) {



        // 保存当前任务列表的引用
        this.currentAllTasks = allTasks;

        // 初始化种群
        Population population = initializePopulation(user, allTasks, taskCacheMap);

        // 进化过程
        for (int generation = 0; generation < maxGenerations; generation++) {
            population = evolvePopulation(population, user, allTasks, taskCacheMap);

            // 可选：输出当前最优解信息
            if (generation % 10 == 0) {
                Chromosome best = population.getFittest(user, taskCacheMap, allTasks);
                log.info("Generation {}: Best Fitness = {}",
                        generation, best.getFitness(user, taskCacheMap, allTasks));
            }
        }

        // 获取最优解并执行分配
        Chromosome bestSolution = population.getFittest(user, taskCacheMap, allTasks);
        return executeBestSolution(bestSolution, user, allTasks, assignmentOutcome, assignmentOutcomeUserService, taskCacheMap, notIncreaseTaskIdSet);
    }

    /**
     * 初始化种群
     */
    private Population initializePopulation(UserAlg user, List<TaskAlg> allTasks, Map<Long, TaskAlg> taskCacheMap) {
        List<Chromosome> chromosomes = new ArrayList<>();

        for (int i = 0; i < populationSize; i++) {
            Chromosome chromosome = new Chromosome(allTasks.size());

            // 随机生成染色体
            Random random = new Random();
            for (int j = 0; j < allTasks.size(); j++) {
                chromosome.genes[j] = random.nextDouble() < 0.3; // 30%概率选择任务
            }

            // 修复染色体（确保满足约束）
            chromosome.repair(user, allTasks, taskCacheMap);
            chromosomes.add(chromosome);
        }

        return new Population(chromosomes);
    }

    /**
     * 种群进化
     */
    private Population evolvePopulation(Population population, UserAlg user,
                                        List<TaskAlg> allTasks, Map<Long, TaskAlg> taskCacheMap) {
        List<Chromosome> newChromosomes = new ArrayList<>();

        // 精英保留
        List<Chromosome> elites = population.getElites(elitismCount, user, taskCacheMap, allTasks);
        newChromosomes.addAll(elites);

        // 交叉和变异生成新个体
        Random random = new Random();
        while (newChromosomes.size() < populationSize) {
            // 选择父代
            Chromosome parent1 = tournamentSelection(population, user, taskCacheMap, allTasks);
            Chromosome parent2 = tournamentSelection(population, user, taskCacheMap, allTasks);

            // 交叉
            Chromosome[] children;
            if (random.nextDouble() < crossoverRate) {
                children = crossover(parent1, parent2);
            } else {
                children = new Chromosome[]{parent1.clone(), parent2.clone()};
            }

            // 变异
            for (Chromosome child : children) {
                if (random.nextDouble() < mutationRate) {
                    mutate(child);
                }
                child.repair(user, allTasks, taskCacheMap);
                newChromosomes.add(child);

                if (newChromosomes.size() >= populationSize) break;
            }
        }

        return new Population(newChromosomes.subList(0, populationSize));
    }

    /**
     * 锦标赛选择
     */
    private Chromosome tournamentSelection(Population population, UserAlg user,
                                           Map<Long, TaskAlg> taskCacheMap, List<TaskAlg> allTasks) {
        Random random = new Random();
        int tournamentSize = 5;
        Chromosome best = null;
        double bestFitness = Double.NEGATIVE_INFINITY;

        for (int i = 0; i < tournamentSize; i++) {
            Chromosome candidate = population.chromosomes.get(random.nextInt(population.chromosomes.size()));
            double fitness = candidate.getFitness(user, taskCacheMap, allTasks);
            if (fitness > bestFitness) {
                bestFitness = fitness;
                best = candidate;
            }
        }

        return best.clone();
    }

    /**
     * 单点交叉
     */
    private Chromosome[] crossover(Chromosome parent1, Chromosome parent2) {
        Random random = new Random();
        int crossoverPoint = random.nextInt(parent1.genes.length);

        Chromosome child1 = parent1.clone();
        Chromosome child2 = parent2.clone();

        for (int i = crossoverPoint; i < parent1.genes.length; i++) {
            boolean temp = child1.genes[i];
            child1.genes[i] = child2.genes[i];
            child2.genes[i] = temp;
        }

        return new Chromosome[]{child1, child2};
    }

    /**
     * 位翻转变异
     */
    private void mutate(Chromosome chromosome) {
        Random random = new Random();
        for (int i = 0; i < chromosome.genes.length; i++) {
            if (random.nextDouble() < mutationRate / chromosome.genes.length) {
                chromosome.genes[i] = !chromosome.genes[i];
            }
        }
    }

    /**
     * 执行最优解
     */
    private List<TaskAlg> executeBestSolution(Chromosome bestSolution, UserAlg user,
                                              List<TaskAlg> allTasks, AssignmentOutcome assignmentOutcome,
                                              AssignmentOutcomeUserService assignmentOutcomeUserService, Map<Long, TaskAlg> taskCacheMap, Set<Long> notIncreaseTaskIdSet) {

        List<TaskAlg> selected = new ArrayList<>();
        double userTotalDeltaF = 0;
        double totalCost = 0;

        // 按染色体选择任务
        for (int i = 0; i < bestSolution.genes.length; i++) {
            if (bestSolution.genes[i]) {
                TaskAlg task = allTasks.get(i); // 现在可以正确访问

                // 检查任务质量增量是否有效
                if (task.totalF > 1) {
                    notIncreaseTaskIdSet.add(task.id);
                    continue;
                }

                double deltaF = task.calDeltaFCommon();
                if (deltaF <= 0) {
                    continue;
                }

                selected.add(task);

                // 更新任务执行次数和质量
                task.k++;
                userTotalDeltaF += deltaF;

                TaskAlg taskCache = taskCacheMap.get(task.id);
                if (taskCache == null) {
                    taskCache = task;
                    taskCacheMap.put(task.id, taskCache);
                } else {
                    taskCache.k++;
                    taskCache.totalF += deltaF;
                }
            }
        }

        // 计算用户任务执行成本和距离成本
        double currentX = user.startX, currentY = user.startY;
        for (TaskAlg task : selected) {
            double distance = calculateDistance(currentX, currentY, task.taskX, task.taskY);
            user.distanceCost += distance;
            user.executionCost += task.executionCost;
        }
        // 添加返回终点的成本
        double finalTailDistance = calculateDistance(currentX, currentY, user.destX, user.destY);
        user.distanceCost += finalTailDistance;
        user.realPath.addAll(selected);
        // 保存用户执行结果详情表
        assignmentOutcomeUserService.saveOutcomeUser(user, assignmentOutcome, selected,userTotalDeltaF);
        log.info("用户[{}]执行平台安排的任务后的质量增量总和为[{}]",user.id,userTotalDeltaF);
        return selected;
    }

    /**
     * 计算总成本（包含旅行路径优化）
     */
    private double calculateTotalCost(List<TaskAlg> tasks, UserAlg user) {
        if (tasks.isEmpty()) return 0;

        // 使用最近邻算法优化路径
        List<TaskAlg> optimizedPath = optimizePath(tasks, user);

        double totalCost = 0;
        double currentX = user.startX, currentY = user.startY;

        // 计算移动成本
        for (TaskAlg task : optimizedPath) {
            double distance = calculateDistance(currentX, currentY, task.taskX, task.taskY);
            totalCost += distance + task.executionCost;
            currentX = task.taskX;
            currentY = task.taskY;
        }

        // 添加返回终点的成本
        double finalTailDistance = calculateDistance(currentX, currentY, user.destX, user.destY);
        totalCost += finalTailDistance;
        return totalCost;
    }

    /**
     * 使用最近邻算法优化路径
     */
    private List<TaskAlg> optimizePath(List<TaskAlg> tasks, UserAlg user) {
        if (tasks.isEmpty()) return tasks;

        List<TaskAlg> optimized = new ArrayList<>();
        List<TaskAlg> remaining = new ArrayList<>(tasks);
        double currentX = user.startX, currentY = user.startY;

        while (!remaining.isEmpty()) {
            // 找最近的任务
            TaskAlg nearest = null;
            double minDistance = Double.MAX_VALUE;

            for (TaskAlg task : remaining) {
                double distance = calculateDistance(currentX, currentY, task.taskX, task.taskY);
                if (distance < minDistance) {
                    minDistance = distance;
                    nearest = task;
                }
            }

            optimized.add(nearest);
            remaining.remove(nearest);
            currentX = nearest.taskX;
            currentY = nearest.taskY;
        }
        tasks.clear();
        tasks.addAll(optimized);
        return tasks;
    }

    /**
     * 染色体类
     */
    private class Chromosome implements Cloneable {
        boolean[] genes;

        Chromosome(int length) {
            this.genes = new boolean[length];
        }

        /**
         * 计算适应度函数
         */
        double getFitness(UserAlg user, Map<Long, TaskAlg> taskCacheMap, List<TaskAlg> allTasks) {
            double totalDeltaF = 0;
            double totalCost = 0;
            List<TaskAlg> selectedTasks = new ArrayList<>();

            // 收集选中的任务
            for (int i = 0; i < genes.length; i++) {
                if (genes[i]) {
                    // 通过参数传入allTasks
                    TaskAlg task = allTasks.get(i);
                    TaskAlg cache = taskCacheMap.get(task.id);
                    if (cache != null) {
                        task.k = cache.k;
                        task.totalF = cache.totalF;
                    }
                    // 检查任务约束
                    if (task.totalF > 1) {
                        continue; // 跳过总质量大于1的任务
                    }

                    double deltaF = task.calDeltaFCommon();
                    if (deltaF <= 0) {
                        continue; // 跳过质量增量非正的任务
                    }

                    selectedTasks.add(task);
                    totalDeltaF += deltaF;
                }
            }

            // 计算总成本
            totalCost = calculateTotalCost(selectedTasks, user);

            // 如果超预算，适应度为负（惩罚）
            if (totalCost > user.budget) {
                return -totalCost / user.budget; // 标准化惩罚
            }

            // 适应度 = 总质量增量 / 总成本（性价比）
            return (totalDeltaF + 0.001) / (totalCost + 0.001); // 避免除零
        }

        /**
         * 修复染色体，确保满足约束
         */
        void repair(UserAlg user, List<TaskAlg> allTasks, Map<Long, TaskAlg> taskCacheMap) {
            List<TaskAlg> selectedTasks = getSelectedTasks(allTasks);
            double currentCost = calculateTotalCost(selectedTasks, user);
            Random random = new Random();

            // 如果超预算，移除任务直到满足预算
            while (currentCost > user.budget && hasSelectedTasks()) {
                List<Integer> selectedIndices = getSelectedIndices();
                if (selectedIndices.isEmpty()) break;

                // 按成本效益比排序，优先移除性价比低的任务
                selectedIndices.sort((idx1, idx2) -> {
                    TaskAlg task1 = allTasks.get(idx1);
                    TaskAlg task2 = allTasks.get(idx2);
                    double utility1 = task1.calDeltaFCommon() / (task1.executionCost + 0.001);
                    double utility2 = task2.calDeltaFCommon() / (task2.executionCost + 0.001);
                    return Double.compare(utility1, utility2); // 升序排列，性价比低的在前
                });

                // 移除性价比最低的任务
                int removeIndex = selectedIndices.get(0);
                genes[removeIndex] = false;

                // 重新计算成本
                selectedTasks = getSelectedTasks(allTasks);
                currentCost = calculateTotalCost(selectedTasks, user);
            }
        }

        private List<TaskAlg> getSelectedTasks(List<TaskAlg> allTasks) {
            List<TaskAlg> selected = new ArrayList<>();
            for (int i = 0; i < genes.length; i++) {
                if (genes[i]) {
                    selected.add(allTasks.get(i));
                }
            }
            return selected;
        }

        private List<Integer> getSelectedIndices() {
            List<Integer> indices = new ArrayList<>();
            for (int i = 0; i < genes.length; i++) {
                if (genes[i]) indices.add(i);
            }
            return indices;
        }

        private boolean hasSelectedTasks() {
            for (boolean gene : genes) {
                if (gene) return true;
            }
            return false;
        }

        @Override
        public Chromosome clone() {
            Chromosome clone = new Chromosome(this.genes.length);
            System.arraycopy(this.genes, 0, clone.genes, 0, this.genes.length);
            return clone;
        }
    }

    /**
     * 种群类
     */
    private class Population {
        List<Chromosome> chromosomes;

        Population(List<Chromosome> chromosomes) {
            this.chromosomes = chromosomes;
        }

        Chromosome getFittest(UserAlg user, Map<Long, TaskAlg> taskCacheMap, List<TaskAlg> allTasks) {
            return chromosomes.stream()
                    .max((c1, c2) -> Double.compare(
                            c1.getFitness(user, taskCacheMap, allTasks),
                            c2.getFitness(user, taskCacheMap, allTasks)))
                    .orElse(chromosomes.get(0));
        }

        List<Chromosome> getElites(int count, UserAlg user,
                                   Map<Long, TaskAlg> taskCacheMap, List<TaskAlg> allTasks) {
            return chromosomes.stream()
                    .sorted((c1, c2) -> Double.compare(
                            c2.getFitness(user, taskCacheMap, allTasks),
                            c1.getFitness(user, taskCacheMap, allTasks)))
                    .limit(count)
                    .map(Chromosome::clone)
                    .collect(Collectors.toList());
        }
    }

    // 从QEA继承的工具方法
    public static double calculateDistance(double x1, double y1, double x2, double y2) {
        return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
    }



}